#include "tcpconnection.h"
#include "asyncservice.h"
#include "tcpacceptor.h"
#include <boost/bind.hpp>

TcpAcceptor::TcpAcceptor(AsyncService &service) :
    m_acceptor(service.implement())
{

}

TcpAcceptor::~TcpAcceptor()
{

}

int TcpAcceptor::open(const std::string &host, unsigned short port, int listenCount)
{
    ErrorCode ec;
        Endpoint ep;

        if(m_acceptor.is_open()){
            return boost::system::errc::already_connected;
        }

        if(host.empty() ||
                !host.compare("0.0.0.0") ||
                !host.compare("any")){
            ep = Endpoint(boost::asio::ip::tcp::v4(), port);
        }else{
            Address addr = Address::from_string(host, ec);

            if(ec){
                return ec.value();
            }

            ep = Endpoint(addr, port);
        }

        m_acceptor.open(boost::asio::ip::tcp::v4(), ec);

        if(ec){
            return ec.value();
        }

        m_acceptor.set_option(Acceptor::reuse_address(true), ec);

        if(ec){
            return ec.value();
        }

        m_acceptor.bind(ep, ec);

        if(ec){
            return ec.value();
        }

        m_acceptor.listen(listenCount ? listenCount : Acceptor::max_connections, ec);

        if(ec){
            return ec.value();
        }

        return 0;
}

void TcpAcceptor::close()
{
    ErrorCode ec;

    m_acceptor.close(ec);
}

void TcpAcceptor::accept(TcpConnection &con, BOOST_ASIO_MOVE_ARG(Accepted) a)
{
    m_acceptor.async_accept
            (
                con.sock(),
                boost::bind
                (
                    &TcpAcceptor::onAccept,
                    this,
                    Accepted(a),
                    _1
                )
            );
}

void TcpAcceptor::onAccept(Accepted a, ErrorCode ec)
{
    a(ec.value());
}
